package com.hundsun.cprs.yyt.service.trade.service.impl;

import com.hundsun.cprs.yyt.common.base.BaseService;
import com.hundsun.cprs.yyt.common.enums.EnumBusinessCode;
import com.hundsun.cprs.yyt.common.exception.ServiceCodeException;
import com.hundsun.cprs.yyt.service.account.enums.EnumQuotaTransType;
import com.hundsun.cprs.yyt.service.account.service.AccountService;
import com.hundsun.cprs.yyt.service.common.dto.FundBatchRequest;
import com.hundsun.cprs.yyt.service.common.dto.UserAccountDTO;
import com.hundsun.cprs.yyt.service.common.enums.EnumFundBidCode;
import com.hundsun.cprs.yyt.service.common.service.RemoteTradeFundService;
import com.hundsun.cprs.yyt.service.common.service.RemoteUserService;
import com.hundsun.cprs.yyt.service.goods.dto.GoodsInfo;
import com.hundsun.cprs.yyt.service.goods.service.GoodsService;
import com.hundsun.cprs.yyt.service.goods.service.GoodsSkuService;
import com.hundsun.cprs.yyt.service.order.domain.OrderItem;
import com.hundsun.cprs.yyt.service.order.dto.OrderInfo;
import com.hundsun.cprs.yyt.service.order.enums.EnumOrderSNCode;
import com.hundsun.cprs.yyt.service.order.enums.EnumsOrderStatus;
import com.hundsun.cprs.yyt.service.order.service.OrderService;
import com.hundsun.cprs.yyt.service.quota.service.QuotaHoldService;
import com.hundsun.cprs.yyt.service.trade.dao.ReturnGoodsFlowDao;
import com.hundsun.cprs.yyt.service.trade.domain.ReturnGoodsFlow;
import com.hundsun.cprs.yyt.service.trade.domain.TradeEntrust;
import com.hundsun.cprs.yyt.service.trade.domain.query.ReturnGoodsFlowQuery;
import com.hundsun.cprs.yyt.service.trade.dto.ReturnGoodsFlowInfo;
import com.hundsun.cprs.yyt.service.trade.enums.EnumReturnGoodsFlowStatus;
import com.hundsun.cprs.yyt.service.trade.enums.EnumTradeEntrustStatus;
import com.hundsun.cprs.yyt.service.trade.enums.EnumTradeStatus;
import com.hundsun.cprs.yyt.service.trade.service.ReturnGoodsFlowService;
import com.hundsun.cprs.yyt.service.trade.service.TradeEntrustService;
import com.hundsun.cprs.yyt.util.SequenceUtils;
import org.apache.commons.lang.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.Date;
import java.util.List;

/**
 * @author herong22384
 * @date 2019/7/23 15:16
 */
@Service
public class ReturnGoodsFlowServiceImpl extends BaseService implements ReturnGoodsFlowService {

    @Autowired
    private ReturnGoodsFlowDao returnGoodsFlowDao;
    @Autowired
    private TradeEntrustService entrustService;
    @Autowired
    private GoodsSkuService goodsSkuService;
    @Autowired
    private RemoteUserService remoteUserService;
    @Autowired
    private RemoteTradeFundService remoteTradeFundService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private QuotaHoldService quotaHoldService;

    @Override
    public void createReturnGoodsFlow(ReturnGoodsFlow returnGoodsFlow) {
        Validate.notNull(returnGoodsFlow.getEntrustId(),"委托单信息不能为空");
        Validate.notEmpty(returnGoodsFlow.getFundAccount(),"用户的资金账号不能为空");
        Validate.notEmpty(returnGoodsFlow.getGoodsCode(),"商品信息不能为空");
        Validate.notNull(returnGoodsFlow.getUserId(),"用户信息不能为空");
        returnGoodsFlow.setStatus(EnumReturnGoodsFlowStatus.WAIT_AUDIT.getCode());
        returnGoodsFlow.setApplyTime(new Date());
        returnGoodsFlow.setSn(SequenceUtils.generateSequence(SequenceUtils.BIZ_RETURN));
        returnGoodsFlowDao.insert(returnGoodsFlow);
    }

    @Override
    public void queryByPage(ReturnGoodsFlowQuery query) {
        List<ReturnGoodsFlowInfo> returnGoodsFlows = returnGoodsFlowDao.queryByPage(query);
        query.compatible(returnGoodsFlows);
    }

    @Override
    public ReturnGoodsFlowInfo getReturnGoodsFlowById(Long id) {
        return returnGoodsFlowDao.selectByPrimaryKey(id);
    }

    @Override
    @Transactional
    public void audit(ReturnGoodsFlow flow,TradeEntrust entrust) {
        try{
            if (flow.getStatus().equals(EnumReturnGoodsFlowStatus.PASS_AUDIT.getCode())){
                //1.将挂售单置为已完成状态
                updateTrusteOrderStatus(entrust);
                //2.有订单的将订单置为已完成状态，并设置订单项中退货信息
                if (flow.getOrderId() != null){
                    //获取订单详情
                    OrderInfo orderInfo = orderService.selectOrderInfoById(flow.getOrderId());
                    //更新订单状态
                    orderInfo = updateOrderStatus(entrust,orderInfo);
                    //更新批发区库存
                    updateSkuStock(orderInfo);
                }
                //3.退配额
                returnQuota(flow);
                //4.资金划拨
                returnBackMoney(flow);
            }else if (flow.getStatus().equals(EnumReturnGoodsFlowStatus.FAIL_AUDIT.getCode())){
                //5.审核不通过不需要单独做额外的动作，仍然保留挂售单的已撤销状态，后续可再次发起退货或者发货

            }else {
                throw new ServiceCodeException(EnumBusinessCode.BUSSINESS_1704.getErrorNo(),EnumBusinessCode.BUSSINESS_1704.getErrorInfo());
            }
            //6.更新退货申请记录的状态
            flow.setAuditTime(new Date());
            returnGoodsFlowDao.updateByPrimaryKeySelective(flow);
        }catch (ServiceCodeException e){
            throw e;
        }catch (Exception e){
            logger.error(e);
            throw e;
        }
    }

    protected void updateTrusteOrderStatus(TradeEntrust tradeEntrust){
        TradeEntrust entrust = new TradeEntrust();
        entrust.setId(tradeEntrust.getId());
        //更新委托单的大类状态和小类状态
        entrust.setStatus(EnumTradeStatus.DEALT.getStatus());
        entrust.setEntrustStatus(EnumTradeEntrustStatus.DEALT.getStatus());
        entrustService.updateEntrustOrder(entrust);
    }

    protected void updateSkuStock(OrderInfo orderInfo){
        //更新商品的预占库存和实际库存
        if (orderInfo != null){
            //更新sku的库存
            OrderItem orderItem = orderInfo.getOrderItems().get(0);
            int outMount = orderItem.getQuantity();//预占库存直接减掉
            int stock = orderItem.getQuantity() - orderItem.getReturnedQuantity().intValue();//退货时实际扣减库存是总量减去退货的数量
            goodsSkuService.deductGoodsStock(orderItem.getSkuId(),outMount,stock);
        }
    }

    protected OrderInfo updateOrderStatus(TradeEntrust tradeEntrust,OrderInfo orderInfo){
        if (orderInfo != null){
            //更新订单状态
            orderInfo.setStatus(EnumsOrderStatus.RETURN.getStatus());
            orderInfo.setCompleteDate(new Date());
            //更新订单项内的退货数量和已成数量
            for (OrderItem orderItem:orderInfo.getOrderItems()){
                Long saledAmount = Math.abs(tradeEntrust.getBusinessAmount());
                orderItem.setReturnedQuantity(tradeEntrust.getEntrustAmount() - saledAmount);
                orderItem.setShippedQuantity(saledAmount);
            }
            orderService.updateOrder(orderInfo);
        }
        return orderInfo;
    }

    protected void returnQuota(ReturnGoodsFlow flow){
        if (flow.getReturnQuoteAmount() > 0){
            quotaHoldService.addQuota(flow.getUserId(),flow.getQuotaId(),flow.getReturnQuoteAmount(),EnumQuotaTransType.TRANS_0201.getCode(),"挂售单退货返还配额");
        }
    }

    protected void returnBackMoney(ReturnGoodsFlow flow){
        Long returnBackMoney = flow.getReturnFundAmount();
        //流水描述
        String memo = MessageFormat.format("[{0}]挂售单退货收入",flow.getGoodsName());
        FundBatchRequest request = FundBatchRequest.builder("system", EnumOrderSNCode.getOrderFundSN(flow.getSn(), EnumOrderSNCode.FUND_IN),memo);
        if (returnBackMoney != null && returnBackMoney > 0){
            //获取到商品的供应商
            List<GoodsInfo> goodsInfos = goodsService.selectGoodsByGoodsCode(flow.getGoodsCode());
            if (CollectionUtils.isEmpty(goodsInfos)){
                throw new ServiceCodeException(EnumBusinessCode.BUSINESS_1102.getErrorNo(),EnumBusinessCode.BUSINESS_1102.getErrorInfo());
            }
            //扣除卖家的退款金额
            UserAccountDTO sellerInfo = remoteUserService.getUserDetailByUserId(goodsInfos.get(0).getOrganizationId().longValue());
            if (sellerInfo == null) {
                throw new ServiceCodeException(EnumBusinessCode.BUSINESS_1001.getErrorNo(),"卖家信息状态异常");
            }
            request.addTask(sellerInfo.getFundAccount(), EnumFundBidCode.CFUND_170201, flow.getSn(), returnBackMoney,"买家订单退货扣款");
            //给买家打款
            request.addTask(flow.getFundAccount(), EnumFundBidCode.CFUND_170102, flow.getSn(), returnBackMoney);
            remoteTradeFundService.batchExecute(request);
        }
    }
}
